package com.xinyue.game.client.network;

import com.xinyue.network.codec.*;
import com.xinyue.network.hamdlermapping.GameChannelContext;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelOutboundHandlerAdapter;
import io.netty.channel.ChannelPromise;
import io.netty.util.Attribute;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @author 王广帅
 * @date 2021年01月28日 12:52 上午
 */
public class EncodeHandler extends ChannelOutboundHandlerAdapter {
    private Logger logger = LoggerFactory.getLogger(EncodeHandler.class);
    private int messageSeqId;

    @Override
    public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
        if (msg instanceof IGameMessage) {
            try {
                IGameMessage gameMessage = (IGameMessage) msg;
                messageSeqId++;
                GameMessageHeader header = new GameMessageHeader();
                header.setSeqId(messageSeqId);
                header.setSendTime(System.currentTimeMillis());
                GameMessageMeta gameMessageMeta = msg.getClass().getAnnotation(GameMessageMeta.class);
                if (gameMessageMeta == null) {
                    throw new IllegalArgumentException("发送的消息未添加消息无数据");
                }
                header.setMessageId(gameMessageMeta.messageId());
                header.setMessageType(gameMessageMeta.messageType());
                Attribute<byte[]> attr = ctx.channel().attr(GameChannelContext.CHANNEL_AES_ENCRYPT_KEY);
                GameMessageContext messageContext = new GameMessageContext(header,attr.get());
                messageContext.setGameMessage(gameMessage);
                ByteBuf byteBuf = GameCodecFactory.writeMessage(messageContext);
                ctx.writeAndFlush(byteBuf, promise);
            } catch (Throwable e) {
                logger.error("向服务器发送消息失败", e);
            }
        } else {
            ctx.write(msg);
        }
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        logger.error("向服务器发送数据失败", cause);
    }
}
